﻿//
// © Algobox Ltd - Benn Eichhorn
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Algobox.Objects.Finance.Assets.Stock;
using Algobox.Feeds.Finance.MarketData;

namespace Algobox.Structure.Finance.Strategies
{
    public class StrategyUnitSummary : INotifyPropertyChanged, IMarketUpdateLast
    {
        #region Constructors

        public StrategyUnitSummary(Strategy strategy, string name)
        {
            _strategy = strategy;
            _name = name;
            if (strategy.Security.Currency == Objects.Finance.Currencies.Currency.GBX)
                _divisor = 100;
            else
                _divisor = 1;                        
        }

        #endregion
        //////////////////
        #region Member Variables

        public event PropertyChangedEventHandler PropertyChanged;

        private readonly object _lock = new object();
        private readonly Strategy _strategy;
        private readonly string _name;
        private int _divisor;
        private long _position;
        private double _entryValue;
        private double _unrealPL;
        private double _realPL;

        #endregion
        //////////////////
        #region Properties

        public string Name { get { return _name; } }
        public long Position { get { return _position; } set { _position = value; NotifyPropertyChanged("Position"); } }
        public double UnrealPL { get { return _unrealPL; } set { _unrealPL = value; NotifyPropertyChanged("UnrealPL"); NotifyPropertyChanged("NetPL"); } }
        public double RealPL { get { return _realPL; } set { _realPL = value; NotifyPropertyChanged("RealPL"); NotifyPropertyChanged("NetPL"); } }
        public double NetPL { get { return _realPL + _unrealPL; } }

        #endregion
        //////////////////
        #region Functions

        internal void AddUnit(IStrategyUnit unit)
        {
            unit.PropertyChanged += new PropertyChangedEventHandler(Unit_PropertyChanged);
        }

        void Unit_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            IStrategyUnit unit = sender as IStrategyUnit;            
            if (unit != null)
            {
                if (e.PropertyName == "EntryActual")
                {
                    lock (_lock)
                    {
                        if (unit.Direction == Side.Long)
                        {
                            Position += (long)unit.Quantity;
                            _entryValue -= unit.Quantity * (unit.EntryActual / _divisor);
                        }
                        else
                        {
                            Position -= (long)unit.Quantity;
                            _entryValue += unit.Quantity * (unit.EntryActual / _divisor);
                        }
                        UnrealPL = _entryValue + (unit.EntryActual / _divisor * _position);
                    }
                }
                else if (e.PropertyName == "ExitActual")
                {
                    lock (_lock)
                    {
                        if (unit.Direction == Side.Long)
                        {
                            Position -= (long)unit.Quantity;
                            _entryValue += unit.Quantity * (unit.EntryActual / _divisor);
                        }
                        else
                        {
                            Position += (long)unit.Quantity;
                            _entryValue -= unit.Quantity * (unit.EntryActual / _divisor);
                        }
                        UnrealPL = _entryValue + (unit.EntryActual / _divisor * _position);
                        RealPL += unit.Profit;
                    }
                }
            }
        }

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public void OnPriceLast(IStock stock, Objects.Finance.Prices.PriceVolume last)
        {
            if(_entryValue != 0 && last.Price != 0 && System.Threading.Monitor.TryEnter(_lock))
            {
                try
                {
                    if (_entryValue != 0 && last.Price != 0 && _position != 0)
                        UnrealPL = _entryValue + (last.Price / _divisor * _position);
                }
                finally
                {
                    System.Threading.Monitor.Exit(_lock);
                }
            }
        }

        #endregion
    }
}
